<script setup lang="ts">
import VuePlayer from '@/components/player/VuePlayer.vue'
import { defineComponent, reactive, ref, ShallowRef, shallowRef, watch, onMounted, onUnmounted, computed } from 'vue'
import { HistoryAv, historyAvControl, historyAvRequest, useQueryDownloadTasksApi } from '@/api/gps/jt808/jt1078'
import moment from 'moment'
import { storeToRefs } from 'pinia'
import { usePlaybackStore } from '@/store/gps/playback'
import Trajectory from '@/components/map-trajectory/trajectory'
import { useGetTrackPosApi } from '@/api/gps/gps'
import { playbackBus } from '@/utils/gps/event'
import DownloadTask from '@/views/dashboard/right/playback/downloadTask.vue'
import TaskTimeline from '@/views/dashboard/right/playback/taskTimeline.vue'

const playbackStore = usePlaybackStore()
const { curRecordData, curPlayBackDeviceImei, playbackList, newlineTime } = storeToRefs(playbackStore)

const name = ['time', 'task', 'download'] as const
type pageName = (typeof name)[number]

const videoRef = ref()
const trajectoryRef = ref()
const activeName = ref<pageName>('time')
const playLocation = ref<number>(0)
const videoState = reactive({
  playing: false,
  preparing: false,
  totalTime: 0,
  playedTime: 0,
  speed: 1,
  over: true,
  playbackTime: '2024-01-01 00:00:00'
})

const curPlayingTs = computed({
  get() {
    return videoState.playedTime + moment.duration(curRecordData.value?.startTimeMoment || 0).as('ms')
  },
  set(value) {
    videoState.playedTime = value - moment.duration(curRecordData.value?.startTimeMoment || 0).as('ms')
  }
})

let channel = 1
let trajectoryTimer
let routeLength = 0
let routeTimeDifference = 0

const currenComponent = shallowRef(TaskTimeline)

// @ts-ignore
const componentList = reactive<{ [name: pageName]: ShallowRef<typeof defineComponent<any>> }>({
  time: shallowRef(TaskTimeline),
  task: shallowRef(DownloadTask)
})

const taskList = ref([])
const stopList = ref([])

watch(
  () => videoState.playing,
  (val) => {
    console.log(videoState.preparing, videoState.over)
    // 不能在准备中和已结束下执行指令发送
    if (!videoState.preparing && !videoState.over) {
      console.log('发送开始或暂停')
      sendHistoryAvControl()
    }
    val ? runCruise() : stopCruise()
  }
)

watch(
  () => videoState.over,
  (val) => {
    if (val) {
      console.log('执行关闭')
      sendHistoryAvControl()
    }
  }
)

watch(curPlayBackDeviceImei, () => {
  videoRef.value.closeVideoWindow()
  trajectoryRef.value.removeLayer()
  playLocation.value = 0
})

onMounted(() => {
  playbackBus.on('queryPlaybackTrack', requestTrack)
  playbackBus.on('playbackRecordSelection', recordSelectionCallback)
})
onUnmounted(() => {
  playbackBus.off('queryPlaybackTrack')
  playbackBus.off('playbackRecordSelection')
})

function initVideo(data: HistoryAv) {
  channel = data.channel
  // queryDownloadTasks()
  videoState.preparing = true
  videoRef.value.init(({ play, fail }) => {
    console.log('开始获取资源')
    historyAvRequest(data)
      .then((res) => {
        play(res.data.historyUrl2, res.data.heartKey)
      })
      .catch(() => {
        fail()
      })
  })
}
function recordSelectionCallback() {
  videoState.over = true
  playLocation.value = 0
  const { mediaType, storageType, streamType, startTimeMoment, endTimeMoment, channel } = curRecordData.value
  routeTimeDifference = moment.duration(endTimeMoment.diff(startTimeMoment)).as('ms')
  videoState.playedTime = newlineTime.value ? newlineTime.value - moment(startTimeMoment).valueOf() : 0
  videoState.totalTime = routeTimeDifference

  setTimeout(() => {
    initVideo({
      imei: curPlayBackDeviceImei.value,
      mediaType,
      storageType,
      streamType,
      startTime: newlineTime.value
        ? moment(newlineTime.value).format('YYYY-MM-DD HH:mm:ss')
        : startTimeMoment.format('YYYY-MM-DD HH:mm:ss'),
      endTime: endTimeMoment.format('YYYY-MM-DD HH:mm:ss'),
      channel
    })
    newlineTime.value = 0
  }, 500)
}

/**
 * 发送指令
 */
function sendHistoryAvControl() {
  console.log('发送指令')
  historyAvControl({
    imei: curPlayBackDeviceImei.value,
    channel,
    playbackMode: videoState.over ? 2 : videoState.playing ? 0 : 1,
    playbackSpeed: videoState.speed,
    playbackTime: videoState.playbackTime
  })
}
let trackData: any = []
/**
 * 获取轨迹记录
 * @param times
 */
async function requestTrack(times: string[]) {
  // console.log(curPlayBackDeviceImei.value, times)
  const { data } = await useGetTrackPosApi({
    imei: curPlayBackDeviceImei.value,
    startTime: times[0],
    endTime: times[1],
    withStop: true,
    withPos: true,
    withTrip: true,
    withAlarm: true
  })
  trackData = data.positions.map((item) => moment(item.deviceTime).valueOf())
  // console.log(data.positions.map(item => item.deviceTime));
  routeLength = data.positions.length
  trajectoryRef.value.init(data)
  stopList.value = data.stops
}
function runCruise() {
  trajectoryTimer = setInterval(() => {
    if (playLocation.value === routeLength) {
      stopCruise()
    }
    const currenMs = videoState.playedTime + curRecordData.value.startTimeMoment?.valueOf()
    playLocation.value = binarySearch(currenMs)
    // console.log(moment(currenMs).format("HH:mm:ss"), playLocation.value);
  }, 1000)
}

function stopCruise() {
  clearInterval(trajectoryTimer)
}

/**
 * 查找
 * @param target
 */
function binarySearch(target) {
  let left = 0
  let right = trackData.length - 1
  while (left <= right) {
    let mid = Math.floor((left + right) / 2)
    if (trackData[mid] === target || mid === left) {
      return mid // 找到目标，返回索引
    } else if (trackData[mid] < target) {
      left = mid + 1 // 在右半区继续查找
    } else {
      right = mid - 1 // 在左半区继续查找
    }
  }
  return 0
}

/**
 * 定点播放
 * @param playbackTime
 * @param playbackMode
 */
function fixedPointPlayback(playbackTime: string, playbackMode: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 0) {
  // historyAvControl({
  //   channel,
  //   imei: curPlayBackDeviceImei.value,
  //   playbackMode,
  //   playbackSpeed: 1,
  //   playbackTime
  // })
}

/**
 * 查询下载任务
 */
function queryDownloadTasks() {
  useQueryDownloadTasksApi(curPlayBackDeviceImei.value).then((res) => {
    taskList.value = res.data
  })
}

function computeTimeLine(playbackList) {
  let newArr: any[] = []
  let tmp = { start: 0, end: 0 }
  for (let i = 0; i < playbackList.length; i++) {
    let item = playbackList[i]
    let start = item.startTimeMoment.format('X')
    let end = item.endTimeMoment.format('X')
    if (start > tmp.end) {
      tmp = { start, end }
      newArr.push(tmp)
    } else {
      tmp.end = end
    }
  }
  return newArr
}

function computeStopTimeLine(list: any[]) {
  let newArr: any[] = []
  for (let i = 0; i < list.length; i++) {
    let item = list[i]
    let start = moment(item.startTime).format('X')
    let end = moment(item.endTime).format('X')
    newArr.push({ start, end })
  }
  return newArr
}

function tabChange(name) {
  currenComponent.value = componentList[name]
}

defineExpose({
  // requestDownload
})
</script>

<template>
  <div class="content">
    <div class="bg">
      <div class="av">
        <VuePlayer ref="videoRef" v-model="videoState" control></VuePlayer>
      </div>
      <div class="map">
        <Trajectory ref="trajectoryRef" v-model="playLocation"></Trajectory>
      </div>
    </div>
    <div class="info">
      <el-tabs v-model="activeName" class="item-padding" @tab-change="tabChange">
        <el-tab-pane label="录像时间" name="time"></el-tab-pane>
        <el-tab-pane label="下载任务" name="task"></el-tab-pane>
        <el-tab-pane label="FTP下载" name="download"></el-tab-pane>
      </el-tabs>
      <component
        :is="currenComponent"
        v-model="curPlayingTs"
        :data="taskList"
        :playback-time-line="computeTimeLine(playbackList)"
        :playback-stop-time-line="computeStopTimeLine(stopList)"
        class="set_height"></component>
    </div>
  </div>
</template>

<style scoped lang="scss">
.content {
  overflow: hidden;
}
.bg {
  display: flex;
  flex-direction: row;
  height: 70%;
  .av {
    flex: 2;
    background-color: #337ecc;
  }
  .map {
    width: 100%;
    flex: 1;
  }
}
.set_height {
  height: calc(100% - 40px);
}
.info {
  height: 30%;
}
</style>
